/**
* 设备管理
*/
<template>
  <div>
    <el-page-header @back="$router.back(-1)" content="设备详情">
    </el-page-header>
    <el-divider></el-divider>
    <el-tabs v-model="activeName" @tab-click="handleClick">
      <el-tab-pane label="基本信息" name="base">
        <el-descriptions
          :column="2"
          border
          :labelStyle="{ 'font-weight': 'bold' }"
        >
          <el-descriptions-item label="设备ID">{{
            deviceDetail.deviceId
          }}</el-descriptions-item>
          <el-descriptions-item label="产品productKey">{{
            deviceDetail.productKey
          }}</el-descriptions-item>
          <el-descriptions-item label="设备deviceName">{{
            deviceDetail.deviceName
          }}</el-descriptions-item>
          <el-descriptions-item label="设备密钥">{{
            deviceDetail.secret
          }}</el-descriptions-item>
          <el-descriptions-item label="创建时间">{{
            deviceDetail.createAt | timestampToTime
          }}</el-descriptions-item>
          <el-descriptions-item label="设备状态">{{
            deviceDetail.state
              ? deviceDetail.state.online
                ? "在线"
                : "离线"
              : "离线"
          }}</el-descriptions-item>
          <el-descriptions-item label="最后上线时间">{{
            deviceDetail.onlineTime | timestampToTime
          }}</el-descriptions-item>
        </el-descriptions>
        <div style="margin: 10px 10px">
          设备标签&nbsp;<el-button
            size="mini"
            icon="el-icon-plus"
            @click="addTag"
          ></el-button>
        </div>

        <el-descriptions
          :column="2"
          border
          :labelStyle="{ 'font-weight': 'bold' }"
        >
          <el-descriptions-item
            v-for="tag in tags"
            :key="tag.name"
            :label="tag.name + '(' + tag.id + ')'"
            >{{ tag.value }}</el-descriptions-item
          >
        </el-descriptions>
      </el-tab-pane>
      <el-tab-pane label="属性" name="property">
        <el-table
          :data="properties"
          border
          v-loading="$store.state.loading"
          style="width: 100%"
        >
          <el-table-column prop="name" label="属性名" width="180">
            <template slot-scope="scope">
              {{ scope.row.name }}({{ scope.row.identifier }})
            </template>
          </el-table-column>
          <el-table-column prop="value" label="属性值" width="180">
            <template slot-scope="scope">
              <span>{{ scope.row.value }} &nbsp;</span>
              <el-button @click="showPropertyHistory(scope.row)" size="mini"
                >历史</el-button
              >
            </template>
          </el-table-column>
          <el-table-column label="可读写">
            <template slot-scope="scope">
              <el-tag
                v-if="!scope.row.write"
                type="info"
                size="mini"
                effect="plain"
                >只读</el-tag
              >
              <el-button
                @click="showWriteProperty(scope.row)"
                v-if="scope.row.write"
                size="mini"
                type="success"
                plain
                >可写</el-button
              >
            </template>
          </el-table-column>
        </el-table>
        <div v-if="!!propertyHistory.name">
          <el-divider></el-divider>
          <el-row>
            <el-col :span="2">
              <h5>历史数据</h5>
            </el-col>
            <el-col :span="9">
              <el-date-picker
                v-model="historyTime"
                type="datetimerange"
                :picker-options="pickerOptions"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                align="right"
                @change="timeRangeChange"
              >
              </el-date-picker>
            </el-col>
            <el-col :span="4">
              <el-radio-group v-model="dataType" size="small">
                <el-radio-button label="">无</el-radio-button>
                <el-radio-button label="stats">统计</el-radio-button>
              </el-radio-group>
            </el-col>
          </el-row>
          <PropertyChart
            :name="propertyHistory.name"
            :properties="propertyHistory.data"
          ></PropertyChart>
        </div>
      </el-tab-pane>
      <el-tab-pane label="服务" name="service">
        <el-table
          :data="services"
          border
          v-loading="$store.state.loading"
          style="width: 100%"
        >
          <el-table-column label="服务名称" width="180">
            <template slot-scope="scope">
              {{ scope.row.name }}({{ scope.row.identifier }})
            </template>
          </el-table-column>
          <el-table-column label="操作" width="100">
            <template slot-scope="scope">
              <el-button
                @click="showInvokeService(scope.row)"
                type="success"
                size="mini"
                plain
                >调用</el-button
              >
            </template>
          </el-table-column>
          <el-table-column label="参数">
            <template slot-scope="scope">
              {{ scope.row.inputData }}
            </template>
          </el-table-column>
        </el-table>
      </el-tab-pane>
      <el-tab-pane label="日志" name="event">
        <el-form :inline="true" :model="formInline" class="user-search">
          <el-form-item>
            <el-select
              size="small"
              v-model="formInline.type"
              placeholder="请选择日志类型"
            >
              <el-option label="所有" value=""></el-option>
              <el-option label="状态" value="state"></el-option>
              <el-option label="事件" value="event"></el-option>
              <el-option label="属性" value="property"></el-option>
              <el-option label="服务" value="service"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="搜索：">
            <el-input
              size="small"
              v-model="formInline.identifier"
              placeholder="日志识符"
            ></el-input>
          </el-form-item>
          <el-form-item>
            <el-button
              size="small"
              type="primary"
              icon="el-icon-search"
              @click="logSearch"
              >搜索</el-button
            >
          </el-form-item>
        </el-form>

        <el-table
          :data="events"
          border
          v-loading="$store.state.loading"
          style="width: 100%"
        >
          <el-table-column label="时间" width="180">
            <template slot-scope="scope">
              {{ scope.row.time | timestampToTime }}
            </template>
          </el-table-column>
          <el-table-column prop="type" label="类型" width="80">
          </el-table-column>
          <el-table-column prop="name" label="名称(标识符)" width="180">
          </el-table-column>
          <el-table-column label="内容">
            <template slot-scope="scope">
              {{ scope.row.content.data }}
            </template>
          </el-table-column>
        </el-table>
        <Pagination :data="formInline" @onPagePaging="getEvents"></Pagination>
      </el-tab-pane>
      <el-tab-pane label="模拟上报">
        <el-table
          size="small"
          :data="modelFunctions"
          highlight-current-row
          v-loading="$store.state.loading"
          border
          element-loading-text="拼命加载中"
          style="width: 100%"
        >
          <el-table-column type="expand" label="上报">
            <template slot-scope="fun">
              <el-form
                v-model="fun.row"
                label-width="80px"
                style="width: 500px"
              >
                <el-form-item label="值" v-if="fun.row.type == 'property'">
                  <el-input v-model="fun.row.value" size="mini"></el-input>
                </el-form-item>
                <el-form-item label="内容" v-else>
                  <el-input
                    type="textarea"
                    v-model="fun.row.content"
                    size="mini"
                    rows="4"
                  ></el-input>
                </el-form-item>
                <el-form-item>
                  <el-button
                    type="primary"
                    size="mini"
                    @click="sendDeviceMsg(fun.row)"
                    >发送</el-button
                  >
                </el-form-item>
              </el-form>
            </template>
          </el-table-column>
          <el-table-column sortable prop="type" label="功能类型" width="100">
          </el-table-column>
          <el-table-column sortable prop="name" label="功能名称" width="180">
          </el-table-column>
          <el-table-column
            sortable
            prop="identifier"
            label="标识符"
            width="150"
          >
          </el-table-column>
          <el-table-column
            sortable
            prop="dataTypeName"
            label="数据类型"
            width="100"
          >
          </el-table-column>
          <el-table-column sortable prop="params" label="数据定义" width="200">
          </el-table-column>
        </el-table>
      </el-tab-pane>
      <el-tab-pane label="设备配置">
        <DeviceConfig :deviceId="deviceId" />
      </el-tab-pane>
    </el-tabs>
    <el-dialog
      :title="title"
      :visible.sync="propertyWriteFormVisible"
      width="40%"
      @click="closeDialog"
    >
      <el-form
        label-width="120px"
        :model="propertyWriteForm"
        ref="propertyWriteForm"
      >
        <div style="display: none">
          <el-input
            size="small"
            v-model="propertyWriteForm.identifier"
            type="hidden"
          ></el-input>
        </div>
        <el-form-item label="属性值" prop="value">
          <el-input
            size="small"
            v-model="propertyWriteForm.value"
            auto-complete="off"
          ></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" @click="closeDialog">取消</el-button>
        <el-button
          size="small"
          type="primary"
          :loading="$store.state.loading"
          class="title"
          @click="submitPropertyWriteForm('propertyWriteForm')"
          >保存</el-button
        >
      </div>
    </el-dialog>

    <el-dialog
      :title="title"
      :visible.sync="serviceFormVisible"
      width="40%"
      @click="closeDialog"
    >
      <el-form label-width="120px" :model="serviceForm" ref="serviceForm">
        <div style="display: none">
          <el-input
            size="small"
            v-model="serviceForm.identifier"
            type="hidden"
          ></el-input>
          <el-input
            size="small"
            v-model="serviceForm.productKey"
            type="hidden"
          ></el-input>
          <el-input
            size="small"
            v-model="serviceForm.deviceName"
            type="hidden"
          ></el-input>
        </div>
        <el-form-item
          v-for="param in serviceForm.params"
          :key="param.identifier"
          :label="param.name + '(' + param.identifier + ')'"
          prop="params"
        >
          <el-input
            size="small"
            v-model="param.value"
            auto-complete="off"
          ></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" @click="closeDialog">取消</el-button>
        <el-button
          size="small"
          type="primary"
          :loading="$store.state.loading"
          class="title"
          @click="submitServiceForm('serviceForm')"
          >保存</el-button
        >
      </div>
    </el-dialog>

    <el-dialog title="添加设备标签" :visible.sync="showAddTag" width="400px">
      <el-form ref="form" :model="tagForm" :rules="rules" label-width="80px">
        <el-form-item label="标签名称" prop="name">
          <el-input size="small" v-model="tagForm.name"></el-input>
        </el-form-item>
        <el-form-item label="标识符" prop="id">
          <el-input size="small" v-model="tagForm.id"></el-input>
        </el-form-item>
        <el-form-item label="标签值" prop="value">
          <el-input size="small" v-model="tagForm.value"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitAddTag" size="small"
            >提交</el-button
          >
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>
import { GetThingModel } from "@/api/productApi";
import {
  DeviceDetail,
  PropertySet,
  DeviceLogs,
  ServiceInvoke,
  GetDevicePropertyHistory,
  DeviceTagAdd,
  SimulateSend,
} from "@/api/deviceApi";
import Pagination from "@/components/Pagination";
import PropertyChart from "./PropertyChart.vue";
import DeviceConfig from "./DeviceConfig.vue";
export default {
  data() {
    return {
      loading: false,
      activeName: "base",
      title: "",
      propertyWriteFormVisible: false,
      propertyWriteForm: {
        identifier: "",
        productKey: "",
        deviceName: "",
        value: "",
      },
      serviceFormVisible: false,
      serviceForm: {
        identifier: "",
        productKey: "",
        deviceName: "",
        params: [],
      },
      showAddTag: false,
      tagForm: {
        name: "",
        identifier: "",
        value: "",
      },
      rules: {
        id: [{ required: true, message: "请输入标识符", trigger: "blur" }],
        name: [{ required: true, message: "请输入标签名称", trigger: "blur" }],
        value: [{ required: true, message: "请输入标签值", trigger: "blur" }],
      },
      deviceId: "",
      deviceDetail: {},
      thingModel: null,
      modelFunctions: [],
      properties: [],
      services: [],
      events: [],
      eventMap: {},
      tags: [],
      formInline: {
        type: "",
        identifier: "",
        page: 1,
        size: 10,
        total: 0,
      },
      deviceLogs: [],
      typeMap: {
        lifetime: "生命周期",
        state: "设备状态",
        property: "属性",
        event: "事件",
        service: "服务",
      },
      propertyHistory: {
        name: "",
        data: [],
      },
      dataType: "",
      currHistoryProperty: {},
      historyTime: [
        new Date(new Date().getTime() - 24 * 3600 * 1000),
        new Date(new Date().getTime() + 24 * 3600 * 1000),
      ],
      pickerOptions: {
        shortcuts: [
          {
            text: "最近1小时",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近6小时",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 6);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近1天",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近5天",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 5);
              picker.$emit("pick", [start, end]);
            },
          },
        ],
      },
    };
  },
  components: {
    Pagination,
    PropertyChart,
    DeviceConfig,
  },
  created() {
    this.getdata();
    this.logSearch();
  },
  methods: {
    getdata() {
      this.deviceId = this.$route.query.deviceId;
      DeviceDetail(this.deviceId).then((res) => {
        if (res.state && res.state.onlineTime) {
          res.onlineTime = res.state.onlineTime;
        } else {
          res.onlineTime = "";
        }
        let prop = res.property || {};
        this.deviceDetail = res;

        //取设备物模型信息
        if (!this.thingModel) {
          GetThingModel(res.productKey).then((data) => {
            let model = data.model;
            this.thingModel = model;
            this.services = model.services;

            this.fillProperty(prop);

            //取物模型功能列表
            data.model = data.model || {
              properties: [],
              events: [],
              services: [],
            };
            data.model.properties = data.model.properties || [];
            data.model.events = data.model.events || [];
            data.model.services = data.model.services || [];
            data.model = JSON.parse(JSON.stringify(data.model));

            model = data.model || {};
            let modelFuncs = [];
            model.properties.forEach((p) => {
              let params = JSON.stringify(p.dataType.specs || "{}");
              modelFuncs.push({
                raw: p,
                type: "property",
                name: p.name,
                identifier: p.identifier,
                dataTypeName: p.dataType.type,
                params: params == "{}" ? "" : params,
                value: "",
              });
            });
            model.events.forEach((e) => {
              let output = {};
              e.outputData.forEach((p) => {
                output[p.identifier] = p.name;
              });
              modelFuncs.push({
                raw: e,
                type: "event",
                name: e.name,
                identifier: e.identifier,
                dataTypeName: "-",
                params: JSON.stringify(output),
                content: JSON.stringify(output),
              });
            });
            model.services.forEach((s) => {
              let input = {};
              (s.inputData || []).forEach((p) => {
                input[p.identifier] = p.name;
              });
              let output = {};
              (s.outputData || []).forEach((p) => {
                output[p.identifier] = p.name;
              });
              modelFuncs.push({
                raw: s,
                type: "service",
                name: s.name + "回复",
                identifier: s.identifier + "_reply",
                dataTypeName: "-",
                params: JSON.stringify(output),
                content: JSON.stringify(output),
              });
            });

            this.modelFunctions = modelFuncs;
          });
        } else {
          this.fillProperty(prop);
        }

        let deviceTag = res.tag;
        this.tags = [];
        for (var p in deviceTag) {
          var tag = deviceTag[p];
          this.tags.push({ id: tag.id, name: tag.name, value: tag.value });
        }
      });
    },
    fillProperty(prop) {
      let model = this.thingModel;
      let props = [];
      model.properties.forEach((p) => {
        props.push({
          identifier: p.identifier,
          name: p.name,
          value: prop[p.identifier],
          write: p.accessMode != "r",
        });
      });
      this.properties = props;
    },
    addTag() {
      this.showAddTag = true;
    },
    submitAddTag() {
      this.tagForm.deviceId = this.deviceId;
      this.$refs["form"].validate((valid) => {
        if (valid) {
          DeviceTagAdd(this.tagForm).then(() => {
            this.$message({
              type: "success",
              message: "添加成功",
            });
            this.getdata();
            this.showAddTag = false;
          });
        }
      });
    },
    logSearch() {
      this.formInline.page = 1;
      this.getEvents();
    },
    getEvents() {
      DeviceLogs(this.deviceId, this.formInline).then((res) => {
        this.formInline.total = res.total;
        let logs = [];
        res.data.map((de) => {
          let row = {
            time: de.time,
            type: this.typeMap[de.type],
            name: "未知事件",
            content: de,
          };
          logs.push(row);

          let modeEvents = this.thingModel.events;
          if (modeEvents && modeEvents.length > 0) {
            modeEvents.forEach((e) => {
              if (de.identifier == e.identifier) {
                row.name = e.name;
                return;
              }
            });
          }
          let modeServices = this.thingModel.services;
          if (de.type == "property") {
            if (de.identifier == "set_reply") {
              row.name = "设置回复";
            } else if (de.identifier == "report") {
              row.name = "上报";
            } else if (de.identifier == "set") {
              row.name = "设置";
            }
          } else if (de.type == "state") {
            if (de.identifier == "online") {
              row.name = "上线";
            } else {
              row.name = "下线";
            }
          } else if (de.type == "lifetime") {
            if (de.identifier == "register") {
              row.name = "注册";
            }
          } else if (modeServices && modeServices.length > 0) {
            var ids = de.identifier.split("_reply");
            modeServices.forEach((e) => {
              if (ids[0] == e.identifier) {
                row.name = e.name + (ids.length > 1 ? "回复" : "");
                return;
              }
            });
          }

          row.name = row.name + "(" + de.identifier + ")";
          return de;
        });

        this.events = logs;
      });
    },
    showPropertyHistory(row) {
      this.currHistoryProperty = row;
      this.refreshPropertyHistory();
    },
    refreshPropertyHistory() {
      var end = this.historyTime[1];
      var start = this.historyTime[0];
      GetDevicePropertyHistory(
        this.deviceId,
        this.currHistoryProperty.identifier,
        start.getTime(),
        end.getTime()
      ).then((res) => {
        this.propertyHistory.name = this.currHistoryProperty.name;
        this.propertyHistory.data = res;
      });
    },
    timeRangeChange() {
      this.refreshPropertyHistory();
    },
    handleClick(tab) {
      if (tab.name == "event") {
        this.getEvents();
      } else {
        this.getdata();
      }
    },
    showWriteProperty(prop) {
      this.propertyWriteFormVisible = true;
      this.title = "设置属性";
      this.propertyWriteForm.identifier = prop.identifier;
      this.propertyWriteForm.productKey = this.deviceDetail.productKey;
      this.propertyWriteForm.deviceName = this.deviceDetail.deviceName;
      this.propertyWriteForm.value = prop.value;
    },
    submitPropertyWriteForm() {
      let form = this.propertyWriteForm;
      let prop = {};
      prop[form.identifier] = form.value;
      PropertySet(this.deviceId, prop).then(() => {
        this.$message({
          type: "info",
          message: "操作成功",
        });
      });
    },
    showInvokeService(service) {
      this.serviceFormVisible = true;
      this.title = "服务调用";
      this.serviceForm.identifier = service.identifier;
      this.serviceForm.deviceId = this.deviceDetail.deviceId;
      let params = [];
      service.inputData.forEach((p) => {
        params.push({
          identifier: p.identifier,
          name: p.name,
          value: "",
        });
      });
      this.serviceForm.params = params;
    },
    submitServiceForm() {
      let form = this.serviceForm;
      let param = {};
      this.serviceForm.params.forEach((p) => {
        param[p.identifier] = p.value;
      });

      ServiceInvoke(this.deviceId, form.identifier, param).then(() => {
        this.$message({
          type: "info",
          message: "操作成功",
        });
      });
    },
    sendDeviceMsg(fun) {
      //发送模拟设备消息
      let data = {};
      if (fun.type == "property") {
        let val = fun.value;
        switch (fun.dataTypeName) {
          case "int32":
          case "bool":
          case "enum":
            val = parseInt(val);
            break;
          case "float":
            val = parseFloat(val);
            break;
        }
        data[fun.identifier] = val;
      } else {
        data = JSON.parse(fun.content);
      }

      SimulateSend(this.deviceId, {
        deviceId: this.deviceId,
        productKey: this.deviceDetail.productKey,
        deviceName: this.deviceDetail.deviceName,
        type: fun.type,
        identifier: fun.type == "property" ? "report" : fun.identifier,
        data: data,
      }).then(() => {
        this.$message({
          type: "info",
          message: "操作成功",
        });
      });
    },
    closeDialog() {
      this.propertyWriteFormVisible = false;
      this.serviceFormVisible = false;
    },
  },
};
</script>